using System;
using System.Collections.Generic;
using System.Text;
using System.Web.UI;
using Microsoft.Practices.CompositeWeb.Interfaces;
using Microsoft.Practices.CompositeWeb;
using Microsoft.Practices.ObjectBuilder;

namespace CompositeWeb.Extensions.Utility
{
    public class UserControlInjectionUtility
    {
        /// <summary>
        /// Execute this method on PrePageExecute event to start the building process
        /// </summary>
        /// <param name="page">The <see cref="System.Web.UI.Page"/> being built</param>
        /// <param name="moduleContainer">The <see cref="Microsoft.Practices.CompositeWeb.Interfaces.ICompositionContainer"/> used for building the page</param>
        /// <param name="pageBuilder">The application's page builder</param>
        /// <example>
        ///protected override void PrePageExecute(Page page)
        ///{
        ///    base.PrePageExecute(page);
        ///    userControlInjectionUtility.PrePageExecute(
        ///        page, 
        ///        GetModuleContainer(new Microsoft.Practices.CompositeWeb.Web.HttpContext(System.Web.HttpContext.Current)), 
        ///        this.PageBuilder);
        ///}
        /// </example>
        public void PrePageExecute(Page page, ICompositionContainer moduleContainer, IBuilder<BuilderStage> pageBuilder)
        {
            page.InitComplete += delegate(object sender, EventArgs e)
            {
                BuildControls(moduleContainer, page.Controls, pageBuilder);
            };
        }

        /// <summary>
        /// Execute this method on PrePageExecute event to tear down the built objects
        /// </summary>
        /// <param name="page">The <see cref="System.Web.UI.Page"/> being built</param>
        /// <param name="moduleContainer">The <see cref="Microsoft.Practices.CompositeWeb.Interfaces.ICompositionContainer"/> used for building the page</param>
        /// <param name="pageBuilder">The application's page builder</param>
        /// <example>
        ///protected override void PostPageExecute(Page page)
        ///{
        ///    base.PostPageExecute(page);
        ///    userControlInjectionUtility.PrePageExecute(
        ///        page, 
        ///        GetModuleContainer(new Microsoft.Practices.CompositeWeb.Web.HttpContext(System.Web.HttpContext.Current)), 
        ///        this.PageBuilder);
        ///}
        /// </example>
        public void PostPageExecute(Page page, ICompositionContainer moduleContainer, IBuilder<BuilderStage> pageBuilder)
        {
            TearDownControls(moduleContainer, page.Controls, pageBuilder);
        }

        private void BuildControls(ICompositionContainer moduleContainer, ControlCollection controls, IBuilder<BuilderStage> pageBuilder)
        {
            foreach (Control control in controls)
            {
                if (control is UserControl)
                {
                    CompositionContainer.BuildItem(pageBuilder, moduleContainer.Locator, control);
                }
                BuildControls(moduleContainer, control.Controls, pageBuilder);
            }
        }

        private void TearDownControls(ICompositionContainer moduleContainer, ControlCollection controls, IBuilder<BuilderStage> pageBuilder)
        {
            foreach (Control control in controls)
            {
                TearDownControls(moduleContainer, control.Controls, pageBuilder);
                if (control is UserControl)
                {
                    pageBuilder.TearDown(moduleContainer.Locator, control); //Context.Handler instead of control??
                }
            }
        }
    }
}
